iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0
AI Security

《30 天打造 AI Guardrails》系列 第 19 篇

Day 19|微調 ShieldGemma:zh-TW injection 資料集準備

  • 分享至 

  • xImage
  •  

微調要解決的問題,先寫清楚

Day 17 的基準測試(未微調)預期會顯示兩個缺口:ShieldGemma 原本是 safety 分類器,對 injection 的判斷靠自訂政策硬套,效果有限;zh-TW 語料的攔截率低於英文。微調的目標就是這兩項,不多——不要順便想把它訓成 PII 偵測器或內容審查器,一個模型一個任務。

資料來源與分割紀律

只用 Day 6 的 tune 分割。再說一次,因為這是最容易犯的錯:eval 集一筆都不能進訓練資料,包括它們的改寫版。

程式層級防護:

# data/build_sft.py
eval_ids = load_ids("corpus/eval.jsonl")
eval_hashes = {norm_hash(x["turns"][-1]["content"]) for x in load("corpus/eval.jsonl")}

for row in load("corpus/tune.jsonl"):
    assert row["id"] not in eval_ids
    assert norm_hash(row["turns"][-1]["content"]) not in eval_hashes, row["id"]

norm_hash 是正規化(去空白、全半形、大小寫)後的雜湊,抓「幾乎一樣」的重複。

資料組成

目標比例(實際筆數依語料建置結果):

來源 標籤 比例目標 用意
D-zh 中文直接注入 Yes 25% 主要缺口
I-doc / I-tool 間接注入 Yes 20% 讓模型看過「藏在正常內容裡」的樣子
M-turn 多輪(展開成最後三輪) Yes 10%
公開英文集抽樣(deepset 等) Yes 10% 維持英文能力不退化
B-benign 高相似負例 No 20% 壓誤判
業務正常語料(去識別化) No 15% 讓模型看過真實正常請求的分布

正負例大約 65 / 35。刻意讓負例比例不要太低,因為 security 場景的誤判代價高(Day 2)。

轉成 ShieldGemma 的訓練格式

訓練樣本就是 Day 18 的 prompt 格式加上答案:

{"text": "<Day 18 的 build_prompt(user_text, POLICY_INJECTION) 輸出>Yes"}
{"text": "<...>No"}

兩個決定:

  1. 政策文字固定。訓練時用同一份 POLICY_INJECTION,推論也用同一份。如果想保留「換政策」的彈性,要在訓練資料裡混入多種政策文字的變體——本系列不做,因為目標單一。
  2. 只訓練答案 token。loss 只算在「Yes」/「No」那個 token 上,prompt 部分 mask 掉。這讓模型學的是判斷,不是背模板。
def to_sft(row):
    prompt = build_prompt(last_user_turn(row), POLICY_INJECTION)
    answer = "Yes" if row["label"] == "attack" else "No"
    return {"prompt": prompt, "completion": answer}

間接注入樣本的包裝

I-doc 與 I-tool 類的 content 是「正常文件 + 藏在裡面的注入」。訓練時要讓模型看到的是它在推論時會看到的樣子——也就是 Day 3 講的「RAG 段落單獨送掃」的那段文字,不是整包 prompt。

def last_user_turn(row):
    if row["context"]["rag_chunks"]:
        return row["context"]["rag_chunks"][0]     # 單段文件作為待判斷內容
    if row["context"]["tool_results"]:
        return json.dumps(row["context"]["tool_results"][0], ensure_ascii=False)
    return row["turns"][-1]["content"]

多輪樣本的展開

M-turn 類展開成「最後三輪拼接」的單段文字,格式跟 Day 9 測 Model Armor 時一致,這樣 Day 28 對照才公平。

資料增強:做與不做

做:

  • 同義改寫(LLM 輔助,人工抽驗 10%)。
  • 位置變體:注入句放在文件開頭/中段/結尾。
  • 格式變體:注入句放在 markdown 註解、HTML 註解、JSON 字串值裡。

不做:

  • 用 LLM 大量生成全新攻擊句——同質性高,而且生成器的偏好會被學進去。
  • 翻譯擴增到 eval 集有的語言以外(本系列只管 zh-TW 與英文)。

驗證集(不是 eval 集)

從 tune 裡切 10% 作為訓練過程的 validation,用來早停與挑 checkpoint。eval 集在 Day 20 才第一次碰。

tune (100%) ──┬── train (90%)
              └── valid (10%)   ← 早停用
eval          ──────────────── ← Day 20 才用,一次

資料集的安全

跟 Day 6 一致:repo 公開資料建置腳本與弱化範例,完整訓練集不公開。

明天預告

Day 20:微調實作與原版對照評估。LoRA 設定、GB10 上的訓練時間、validation 曲線,然後——第一次也是唯一一次——跑 eval 集,跟原版 ShieldGemma 和 Model Armor 三方對照。


追蹤 AId3fend

Instagram @aid3fend
更多 AI 資安筆記:aid3fend.com


上一篇
Day 18|ShieldGemma 在 GB10 上的推論部署與延遲量測
下一篇
Day 20|微調實作與原版對照評估
系列文
《30 天打造 AI Guardrails》 共 21 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言